/*
 * @Author: zhangchaosen
 * @Date: 2024-05-20 09:29:52
 * @LastEditors: zhangchaosen
 * @LastEditTime: 2024-05-20 10:02:01
 * @Description:
 */
import { ElMessage } from 'element-plus'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

import router from '@/router'
import { useUserStoreHook } from '@/store/modules/user'
import { usePermissionStoreHook } from '@/store/modules/permission'
import { getToken } from '@/utils/cookies'
import { getPageTitle } from '@/utils/get-title'
import routeSettings from '@/config/route'
import isWhiteList from '@/config/white-list'

NProgress.configure({ showSpinner: false })

router.beforeEach(async (to, from, next) => {
  NProgress.start()

  const token = getToken()

  // 用户未登录
  if (!token) {
    // 如果在免登录的白名单中，则直接进入
    if (isWhiteList(to)) {
      next()
    } else {
      // 其他没有访问权限的页面将被重定向到登录页面
      NProgress.done()
      next(`/login`)
    }
    return
  }

  // 如果已经登录，并准备进入 Login 页面，则重定向到主页
  if (to.path === '/login') {
    NProgress.done()
    return next({ path: '/' })
  }

  const userStore = useUserStoreHook()

  // 判断用户资料是否获取
  if (userStore.getHasUerInfo) {
    return next()
  }

  // 否则要重新获取用户信息
  try {
    const permissionStore = usePermissionStoreHook()

    if (routeSettings.async) {
      // 注意：角色必须是一个数组！ 例如: ['admin'] 或 ['developer', 'editor']
      await userStore.getLoginUserInfo()
      const roles = userStore.permissions
      // 根据角色生成可访问的 Routes（可访问路由 = 常驻路由 + 有访问权限的动态路由）
      permissionStore.setRoutes(roles)
    } else {
      // 没有开启动态路由功能，则启用默认角色
      permissionStore.setRoutes(routeSettings.defaultRoles)
    }
    // 将'有访问权限的动态路由' 添加到 Router 中
    permissionStore.dynamicRoutes.forEach(route => router.addRoute(route))
    // 确保添加路由已完成
    // 设置 replace: true, 因此导航将不会留下历史记录
    next({ ...to, replace: true })
  } catch (err: any) {
    // 过程中发生任何错误，都直接重置 Token，并重定向到登录页面
    await userStore.resetToken()
    ElMessage({ type: 'error', message: err.message || '路由守卫过程发生错误' })
    NProgress.done()
    next('/login')
  }
})

router.afterEach(to => {
  // 设置页面标题
  document.title = getPageTitle(to.meta.title)
  // 清除请求
  // useRequestStoreHook().clear()
  // 结束进度条
  NProgress.done()
})
